package com.lin.filegraph.utils.componentRule;

import com.lin.filegraph.utils.cluster.ClusterPreJudge;
import com.lin.filegraph.utils.compdg.ComponentGraph;
import com.lin.filegraph.utils.compdg.ComponentNode;

import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

/**
 * @description:
 * @author: linhuaixu
 * @time: 2023/5/18 16:10
 */

public class DetectTransDepend {
    public static void removeOL(ComponentGraph graph) {
        List<ComponentNode> hNode = getHeadNode(graph);
        for(ComponentNode cn:hNode){
            while(execute(graph, cn)){}
        }
    }

    private static boolean execute(ComponentGraph graph, ComponentNode hNode) {
        if (hNode != null) {
            ArrayList<ArrayList<String>> listPaths = new ArrayList<>();
            ArrayList<String> path = new ArrayList<>();
            travelPath(graph, hNode, listPaths, path, 0);
            for (int i = 0; i < listPaths.size(); i++) {
                for (int j = i + 1; j < listPaths.size(); j++) {
                    path =hasSharedNode(listPaths.get(i), listPaths.get(j));
                    if(path!=null){
                        if(enableClusterPath(graph, path)){
                            clusterPath(graph, path);
                            return true;
                        }
                    }
                }
            }
        }
        return false;
    }

    private static void travelPath(ComponentGraph graph, ComponentNode hNode, ArrayList<ArrayList<String>> listPaths, ArrayList<String> path, int sum) {
        //每走一步就添加一个list
        sum++;
        ArrayList<String> tempList = (ArrayList<String>) path.clone();
        for (int i = 0; i < graph.getPostComponents(hNode).size(); i++) {
            ComponentNode cNode = graph.getPostComponents(hNode).get(i);
            if (!cNode.isRegion()) {
                path = (ArrayList<String>) tempList.clone();
                path.add(cNode.getStrComponentName());
                if(path!=null)
                    listPaths.add(path);
                if (sum <= 3) {
                    travelPath(graph, cNode, listPaths, path, sum);
                }
            }
        }
    }

    private static List<ComponentNode> getHeadNode(ComponentGraph graph) {
        List<ComponentNode> hNode = new ArrayList<>();
        // 规模最大域节点
        for (ComponentNode cn : graph.getAllComponents()) {
            if (cn.isRegion()) {
                hNode.add(cn);
            }
        }
        return hNode;
    }

    private static boolean enableClusterPath(ComponentGraph graph, ArrayList<String> listPath) {
        for (int i = 0; i < listPath.size(); i++) {
            ComponentNode node1 = graph.getComponentByName(listPath.get(i));
            for (int j = i + 1; j < listPath.size(); j++) {
                ComponentNode node2 = graph.getComponentByName(listPath.get(j));
                if (!ClusterPreJudge.enableCluster(node1, node2, graph))
                    return false;
            }
        }
        return true;
    }

    private static void clusterPath(ComponentGraph graph, ArrayList<String> listPath) {
        ComponentNode node1 = graph.getComponentByName(listPath.get(0));
        for (int i = 1; i < listPath.size(); i++) {
            ComponentNode node2 = graph.getComponentByName(listPath.get(i));
            graph.mergeNodes(node1, node2);
        }
    }

    private static ArrayList<String> hasSharedNode(ArrayList<String> listPath1, ArrayList<String> listPath2) {
        int length1 = listPath1.size();
        int length2 = listPath2.size();
        Set<String> target = new LinkedHashSet<>();
        target.addAll(listPath1);
        target.addAll(listPath2);
        if (target.size() == (length1 + length2 - 1)) {
            if (listPath1.get(length1 - 1).equals(listPath2.get(length2 - 1))) {
                return new ArrayList<>(target);
            }
        }
        return null;
    }
}

